#pragma once
#include <i_component_factory.h>
#include <i_dll.h>

class CComponentFactoryCenter;
class CComponentContainer;

class CComponentPackage : public IComponentPackage
{
public:
	CComponentPackage(CComponentFactoryCenter& center);
	virtual ~CComponentPackage();

	virtual bool Export(const CComponentFactoryPtr& factory_ptr);

	const std::string& GetFilePath() const {
		return m_filepath;
	}

	const std::string& GetFileName() const {
		return m_filename;
	}

	int64_t GetFileTime() const {
		return m_filetime;
	}

	bool HasRef() const {
		return m_ref_count != 0;
	}

	bool Load(const std::string& filepath);

	void Unload();

	void Register();

	void OnFactoryLoad(const CComponentFactoryPtr& factory_ptr);
	void OnFactoryUnload(const CComponentFactoryPtr& factory_ptr);

protected:
	int m_ref_count;
	int64_t m_filetime;
	std::string m_filename;
	std::string m_filepath;
	CComponentFactoryCenter* const m_center;
	std::unordered_map<std::string, CComponentFactoryPtr> m_factories;
	dll::IDllFilePtr m_dll_file;
};

typedef std::unique_ptr<CComponentPackage> CComponentPackageUniquePtr;


class CComponentFactoryCenter : public IComponentFactoryCenter
{
public:
	CComponentFactoryCenter();
	~CComponentFactoryCenter();

	virtual bool LoadPackage(const std::string& filepath) override;

	virtual int LoadDir(const std::string& dir_path) override;

	virtual bool UnloadPackage(const std::string& filename) override;

	virtual IComponentContainerPtr CreateContainer() override;

	void RemovePackage(const std::string& filename);

	bool RegisterFactory(const CComponentFactoryPtr& factory);

	void UnregisterFactory(const CComponentFactoryPtr& factory);

	const CComponentFactoryPtr& FindComponentFactory(const std::string& component_name) const;

	void CreateComponents(CComponentContainer& container);
protected:
	std::unordered_map<std::string, CComponentPackageUniquePtr> m_packages;
	std::unordered_map<std::string, CComponentFactoryPtr> m_factory_map;
};
